package com.eagle.videoboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.eagle.videoboot.constants.Constant;
import com.eagle.videoboot.domain.entity.Users;
import com.eagle.videoboot.domain.entity.UsersFans;
import com.eagle.videoboot.domain.entity.UsersLikeVideos;
import com.eagle.videoboot.domain.entity.UsersReport;
import com.eagle.videoboot.domain.vo.UsersVO;
import com.eagle.videoboot.exception.ServiceException;
import com.eagle.videoboot.mapper.UsersMapper;
import com.eagle.videoboot.service.IUsersFansService;
import com.eagle.videoboot.service.IUsersLikeVideosService;
import com.eagle.videoboot.service.IUsersReportService;
import com.eagle.videoboot.service.IUsersService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.eagle.videoboot.utils.MD5Utils;
import org.apache.commons.lang3.StringUtils;
import org.n3r.idworker.Sid;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author eagle
 * @since 2020-04-22
 */
@Service
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements IUsersService {

	@Autowired(required = false)
	private UsersMapper userMapper;

	@Resource
	private RedisTemplate<String, Object> redisTemplate;

	@Autowired(required = false)
	private Sid sid;

	@Autowired
	private IUsersFansService usersFansServiceImpl;

	@Autowired
	private IUsersLikeVideosService usersLikeVideosServiceImpl;

	@Autowired
	private IUsersReportService usersReportServiceImpl;



	@Transactional(propagation = Propagation.SUPPORTS)
	@Override
	public boolean queryUsernameIsExist(String username) {
		QueryWrapper<Users> wrapper = new QueryWrapper<>();
		wrapper.eq("username",username);
		Users user = this.getOne(wrapper);

		return user == null ? false : true;
	}

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void saveUser(Users user) throws Exception {
		String userId = sid.nextShort();
		user.setId(userId);
		user.setNickname(user.getUsername());
		user.setPassword(MD5Utils.getMD5Str(user.getPassword()));
		user.setFansCounts(0);
		user.setReceiveLikeCounts(0);
		user.setFollowCounts(0);
		userMapper.insert(user);
	}

	public UsersVO setUserRedisSessionToken(Users userModel) {
		String uniqueToken = UUID.randomUUID().toString();

		redisTemplate.opsForValue().set(
				Constant.USER_REDIS_SESSION + ":" + userModel.getId(),
				uniqueToken, 1000 * 60 * 30, TimeUnit.SECONDS);

		UsersVO userVO = new UsersVO();
		BeanUtils.copyProperties(userModel, userVO);
		userVO.setUserToken(uniqueToken);
		return userVO;
	}

	@Override
	public boolean delUserRedisSessionToken(String userId) {
		Boolean result = redisTemplate.delete(Constant.USER_REDIS_SESSION + ":" + userId);
		return result.booleanValue();
	}

	@Transactional(propagation = Propagation.SUPPORTS)
	@Override
	public Users queryUserForLogin(String username, String password) {
		QueryWrapper<Users> wrapper = new QueryWrapper<>();
		wrapper.eq("username",username).eq("password", password);
		Users user = this.getOne(wrapper);

		return user;
	}

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void updateUserInfo(Users user) {
		QueryWrapper<Users> wrapper = new QueryWrapper<>();
		wrapper.eq("id", user.getId());
		Users one = this.getOne(wrapper);
		if (null != one){
			one.setFaceImage(user.getFaceImage());
			this.updateById(one);
		}else{
			throw new ServiceException("无该用户信息");
		}
	}

	@Transactional(propagation = Propagation.SUPPORTS)
	@Override
	public Users queryUserInfo(String userId) {
		QueryWrapper<Users> wrapper = new QueryWrapper<>();
		wrapper.eq("id",userId);
		Users user = this.getOne(wrapper);
		return user;
	}

	@Override
	public boolean queryIfFollow(String userId, String fanId) {

		QueryWrapper<UsersFans> wrapper = new QueryWrapper<>();

		wrapper.eq("user_id", userId);
		wrapper.eq("fan_id", fanId);

		List<UsersFans> list = usersFansServiceImpl.list(wrapper);

		if (list != null && !list.isEmpty() && list.size() > 0) {
			return true;
		}
		return false;
	}

	@Transactional(propagation = Propagation.SUPPORTS)
	@Override
	public boolean isUserLikeVideo(String userId, String videoId) {

		if (StringUtils.isBlank(userId) || StringUtils.isBlank(videoId)) {
			return false;
		}

		QueryWrapper<UsersLikeVideos> wrapper = new QueryWrapper<>();
		wrapper.eq("user_id", userId);
		wrapper.eq("video_id", videoId);
		List<UsersLikeVideos> list = usersLikeVideosServiceImpl.list(wrapper);

		if (list != null && list.size() >0) {
			return true;
		}

		return false;
	}

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void saveUserFanRelation(String userId, String fanId) {

		String relId = sid.nextShort();

		UsersFans userFan = new UsersFans();
		userFan.setId(relId);
		userFan.setUserId(userId);
		userFan.setFanId(fanId);

		//step 1
		usersFansServiceImpl.save(userFan);
		//step 2
		userMapper.addFansCount(userId);
		//step 3
		userMapper.addFollersCount(fanId);

	}

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void deleteUserFanRelation(String userId, String fanId) {
		QueryWrapper<UsersFans> wrapper = new QueryWrapper<>();
		wrapper.eq("user_id", userId);
		wrapper.eq("fan_id", fanId);
		//step 1
		usersFansServiceImpl.remove(wrapper);
		//step 2
		userMapper.reduceFansCount(userId);
		//step 3
		userMapper.reduceFollersCount(fanId);

	}

	@Transactional(propagation = Propagation.REQUIRED)
	@Override
	public void reportUser(UsersReport userReport) {
		String urId = sid.nextShort();
		userReport.setId(urId);
		userReport.setCreateDate(LocalDateTime.now());
		usersReportServiceImpl.save(userReport);
	}


}
